import numpy as np

def loadsimpData():
    datMat = [[1.0, 2.1],
             [2.0, 1.1],
             [1.3, 1.0],
             [1.0, 1.0],
             [2.0, 1.0]]
    classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
    return datMat, classLabels

def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):
    retArray = np.ones((dataMatrix.shape[0], 1))
    if threshIneq == 'lt':
        retArray[dataMatrix[:, dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:, dimen] > threshVal] = -1.0
    return retArray

def buildStump(dataArr, classLabels, D):
    # 将输入的数据数组dataArr转换为NumPy数组dataMatrix，这样便于进行矩阵运算。
    # 将类别标签classLabels转换为NumPy数组，并且通过reshape(-1,1)将其转换为列向量（即m行1列，m为样本数）。
    # 获取数据矩阵dataMatrix的形状，m为样本数量（行数），n为特征数量（列数）。
    dataMatrix = np.array(dataArr)
    labelMat = np.array(classLabels).reshape(-1, 1)  # 转换为列向量
    m, n = dataMatrix.shape
    
    numSteps = 10.0
    bestStump = {}
    bestClassEst = np.zeros((m, 1))
    minError = np.inf
    
    # 确保D是正确形状的列向量
    if D.ndim == 1:
        D = D.reshape(-1, 1)
    
    for i in range(n):  # 遍历所有特征
        col = dataMatrix[:, i]
        rangeMin = col.min()
        rangeMax = col.max()
        stepSize = (rangeMax - rangeMin) / numSteps
        
        for j in range(-1, int(numSteps) + 1):
            threshVal = rangeMin + j * stepSize
            for inequal in ['lt', 'gt']:
                predictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)
                
                # 计算错误向量
                errArr = np.ones((m, 1))
                errArr[predictedVals == labelMat] = 0
                
                # 修正加权错误计算：确保D和errArr形状兼容
                weightedError = np.sum(D * errArr)
                
                if weightedError < minError:
                    minError = weightedError
                    bestClassEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    
    return bestStump, minError, bestClassEst

if __name__ == "__main__":
    data_matrix, labels = loadsimpData()
    print("数据矩阵：", data_matrix)
    print("标签列表：", labels)
    
    # 修正权重初始化：使用数组并确保正确形状
    D = np.ones((5, 1)) / 5  # 初始权重分布 (5x1列向量)
    
    stump, error, classEst = buildStump(data_matrix, labels, D)
    print("最佳决策树桩:", stump)
    print("最小错误率:", error)
    print("类别估计值:\n", classEst)